home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DDJMAG / DDJ9212.ZIP / cprog.asc < prev    next >
Text File  |  1992-11-30  |  15KB  |  635 lines

  1. _C PROGRAMMING COLUMN_
  2. by Al Stevens
  3.  
  4. [LISTING ONE]
  5.  
  6. // --------------- desktop.cpp
  7.  
  8. #include <new.h>
  9. #include "desktop.h"
  10.  
  11. DeskTop desktop;
  12.  
  13. #ifdef MSC
  14. int NoMemory(unsigned int)
  15. {
  16.     exit(-1);
  17.     return 0;
  18. }
  19. #else
  20. void NoMemory()
  21. {
  22.     exit(-1);
  23. }
  24. #endif
  25. DeskTop::DeskTop()
  26. {
  27.     apwnd = infocus = firstcapture = focuscapture = NULL;
  28. #ifdef MSC
  29.     _set_new_handler(&NoMemory);
  30. #else
  31.     set_new_handler(NoMemory);
  32. #endif
  33.     syscursor.Hide();
  34. }
  35. DeskTop::~DeskTop()
  36. {
  37.     syscursor.Show();
  38. }
  39. Bool DeskTop::DispatchEvents()
  40. {
  41.     syskeyboard.DispatchEvent();
  42.     sysmouse.DispatchEvent();
  43.     sysclock.DispatchEvent();
  44.     return (Bool) (apwnd != NULL);
  45. }
  46.  
  47.  
  48.  
  49. [LISTING TWO]
  50.  
  51. // ----------- screen.cpp
  52.  
  53. #include <string.h>
  54. #include "desktop.h"
  55.  
  56. Screen::Screen()
  57. {
  58.     if (isEGA() || isVGA())    {
  59.         // --- turn blinking off
  60.         regs.x.ax = 0x1003;
  61.         regs.h.bl = 0;
  62.         int86(VIDEO, ®s, ®s);
  63.     }
  64.     // ---- get the video mode and page
  65.     regs.h.ah = 15;
  66.     int86(VIDEO, ®s, ®s);
  67.     mode = regs.h.al;
  68.     page = regs.x.bx;
  69.     page &= 0xff00;
  70.     mode &= 0x7f;
  71.     // ---- Monochrome Display Adaptor or text mode
  72.     if (isMono())
  73.         address = 0xb000;
  74.     else
  75.         // ------ Text mode
  76.         address = 0xb800 + page;
  77.     width = *(unsigned char far *)( MK_FP(0x40,0x4a) );
  78.     if (isVGA() || isEGA())
  79.         height = *(unsigned char far *)( MK_FP(0x40,0x84) )+1;
  80.     else
  81.         height = 25;
  82. }
  83. // ---- test for EGA
  84. Bool Screen::isEGA(void)
  85. {
  86.     if (isVGA())
  87.         return False;
  88.     regs.h.ah = 0x12;
  89.     regs.h.bl = 0x10;
  90.     int86(VIDEO, ®s, ®s);
  91.     return (Bool) (regs.h.bl != 0x10);
  92. }
  93. // ---- test for VGA
  94. Bool Screen::isVGA(void)
  95. {
  96.     regs.x.ax = 0x1a00;
  97.     int86(VIDEO, ®s, ®s);
  98.     return (Bool) (regs.h.al == 0x1a && regs.h.bl > 6);
  99. }
  100. // --------- scroll the screen d: 1 = up, 0 = dn
  101. void Screen::Scroll(Rect &rc, int d, int fg, int bg)
  102. {
  103.     desktop.mouse().Hide();
  104.     regs.h.cl = rc.Left();
  105.     regs.h.ch = rc.Top();
  106.     regs.h.dl = rc.Right();
  107.     regs.h.dh = rc.Bottom();
  108.     regs.h.bh = clr(fg,bg);
  109.     regs.h.ah = 7 - d;
  110.     regs.h.al = 1;
  111.     int86(VIDEO, ®s, ®s);
  112.     desktop.mouse().Show();
  113. }
  114. // -------- read a character of video memory
  115. unsigned int Screen::GetVideoChar(int x, int y)
  116. {
  117.     int c;
  118.     desktop.mouse().Hide();
  119.     c = peek(address, vad(x,y));
  120.     desktop.mouse().Show();
  121.     return c & 255;
  122. }
  123. // -------- write a character of video memory
  124. void Screen::PutVideoChar(int x, int y, unsigned int c)
  125. {
  126.     if (x < width && y < height)    {
  127.         desktop.mouse().Hide();
  128.         poke(address, vad(x,y), c);
  129.         desktop.mouse().Show();
  130.     }
  131. }
  132. // --------- Write a string to video memory
  133. void Screen::WriteVideoString(char *s,int x,int y,int fg,int bg)
  134. {
  135.     if (x < width && y < height)    {
  136.         int len = strlen(s);
  137.         int *ln = new int[len];
  138.         int *cp1 = ln;
  139.         int col = clr(fg,bg) << 8;
  140.         while (*s)    {
  141.             *cp1++ = (*s & 255) | col;
  142.             s++;
  143.         }
  144.         if (x + len >= width)
  145.             len = width - x;
  146.         desktop.mouse().Hide();
  147.         movedata(FP_SEG(ln),FP_OFF(ln),address,vad(x,y),len*2);
  148.         desktop.mouse().Show();
  149.         delete [] ln;
  150.     }
  151. }
  152. // -- read a rectangle of video memory into a save buffer
  153. void Screen::GetBuffer(Rect &rc, char *bf)
  154. {
  155.     if (rc.Left() >= width || rc.Top() >= height)
  156.         return;
  157.     int ht = rc.Bottom()-rc.Top()+1;
  158.     int bytes_row = (rc.Right()-rc.Left()+1) * 2;
  159.     unsigned vadr = vad(rc.Left(), rc.Top());
  160.     desktop.mouse().Hide();
  161.     while (ht--)    {
  162.         movedata(address, vadr, FP_SEG(bf),
  163.                 FP_OFF(bf), bytes_row);
  164.         vadr += width*2;
  165.         bf = (char far *)bf + bytes_row;
  166.     }
  167.     desktop.mouse().Show();
  168. }
  169. // -- write a rectangle of video memory from a save buffer
  170. void Screen::PutBuffer(Rect &rc, char *bf)
  171. {
  172.     if (rc.Left() >= width || rc.Top() >= height)
  173.         return;
  174.     int ht = rc.Bottom()-rc.Top()+1;
  175.     int bytes_row = (rc.Right()-rc.Left()+1) * 2;
  176.     unsigned vadr = vad(rc.Left(), rc.Top());
  177.     desktop.mouse().Hide();
  178.     while (ht--)    {
  179.         movedata(FP_SEG(bf), FP_OFF(bf), address,
  180.                 vadr, bytes_row);
  181.         vadr += width*2;
  182.         bf += bytes_row;
  183.     }
  184.     desktop.mouse().Show();
  185. }
  186.  
  187.  
  188.  
  189.  
  190. [LISTING THREE]
  191.  
  192. // ------------- mouse.cpp
  193.  
  194. #include <stdio.h>
  195. #include "desktop.h"
  196.  
  197. // -------- mouse constructor
  198. Mouse::Mouse()
  199. {
  200.     // ------- see if mouse driver is installed
  201.     unsigned char far *ms;
  202.     ms = (unsigned char far *)
  203.         MK_FP(peek(0, MOUSE*4+2), peek(0, MOUSE*4));
  204.     // --- if the interrupt vector is null or points to a retf,
  205.     //     the mouse driver is not installed
  206.     installed = (Bool) (ms != NULL && *ms != 0xcf);
  207.  
  208.     if (installed)    {
  209.         // --- get the mouse state buffer size
  210.         CallMouse(BUFFSIZE);
  211.         statebuffer = new char[regs.x.bx];
  212.         // --- save the mouse state
  213.         CallMouse(SAVESTATE, 0, 0,
  214.             FP_OFF(statebuffer), FP_SEG(statebuffer));
  215.         // --- reset the mouse
  216.         CallMouse(RESETMOUSE);
  217.         prevx = prevy =
  218.         clickx = clicky =
  219.         releasex = releasey -1;
  220.         SetTravel(0, desktop.screen().Width()-1, 0, 
  221.                                                   desktop.screen().Height()-1);
  222.     }
  223. }
  224. Mouse::~Mouse()
  225. {
  226.     if (installed)    {
  227.         Hide();
  228.         // --- restore the mouse state
  229.         CallMouse(RESTORESTATE, 0, 0,
  230.             FP_OFF(statebuffer), FP_SEG(statebuffer));
  231.         delete [] statebuffer;
  232.     }
  233. }
  234. void Mouse::GetPosition(int &mx, int &my)
  235. {
  236.     mx = my = 0;
  237.     if (installed)    {
  238.         CallMouse(READMOUSE);
  239.         mx = regs.x.cx/8;
  240.         my = regs.x.dx/8;
  241.         if (desktop.screen().Width() == 40)
  242.             mx /= 2;
  243.     }
  244. }
  245. void Mouse::SetPosition(int x, int y)
  246. {
  247.     if (installed)    {
  248.         if (desktop.screen().Width() == 40)
  249.             x *= 2;
  250.         CallMouse(SETPOSITION,0,x*8,y*8);
  251.     }
  252. }
  253. Bool Mouse::Moved()
  254. {
  255.     int x, y;
  256.     Bool rtn = False;
  257.     if (installed)    {
  258.         GetPosition(x, y);
  259.         rtn = (Bool) (x != prevx || y != prevy);
  260.         prevx = x;
  261.         prevy = y;
  262.     }
  263.     return rtn;
  264. }
  265. void Mouse::Show()
  266. {
  267.     if (installed)
  268.         CallMouse(SHOWMOUSE);
  269. }
  270. void Mouse::Hide()
  271. {
  272.     if (installed)
  273.         CallMouse(HIDEMOUSE);
  274. }
  275. Bool Mouse::LeftButton()
  276. {
  277.     Bool rtn = False;
  278.     if (installed)    {
  279.         CallMouse(READMOUSE);
  280.         rtn = (Bool) ((regs.x.bx & 1) == 1);
  281.     }
  282.     return rtn;
  283. }
  284. Bool Mouse::ButtonReleased()
  285. {
  286.     Bool rtn = False;
  287.     if (installed)    {
  288.         CallMouse(BUTTONRELEASED);
  289.         rtn = (Bool) (regs.x.bx != 0);
  290.     }
  291.     return rtn;
  292. }
  293. void Mouse::SetTravel(int minx, int maxx, int miny, int maxy)
  294. {
  295.     if (installed)    {
  296.         if (desktop.screen().Width() == 40)    {
  297.             minx *= 2;
  298.             maxx *= 2;
  299.         }
  300.         CallMouse(XLIMIT, 0, minx*8, maxx*8);
  301.         CallMouse(YLIMIT, 0, miny*8, maxy*8);
  302.     }
  303. }
  304. void Mouse::CallMouse(int m1,int m2,int m3,int m4, unsigned es)
  305. {
  306.     struct SREGS sregs;
  307.     segread(&sregs);
  308.     if (es != 0)
  309.         sregs.es = es;
  310.     regs.x.dx = m4;
  311.     regs.x.cx = m3;
  312.     regs.x.bx = m2;
  313.     regs.x.ax = m1;
  314.     int86x(MOUSE, ®s, ®s, &sregs);
  315. }
  316. // ------ get the window to send mouse events
  317. DFWindow *Mouse::MouseWindow(int mx, int my)
  318. {
  319.     DFWindow *Mwnd;
  320.     if (desktop.FocusCapture() != NULL)
  321.         Mwnd = desktop.FocusCapture();
  322.     else
  323.         Mwnd = inWindow(mx, my);
  324.     return Mwnd;
  325. }
  326. void Mouse::DispatchRelease()
  327. {
  328.     if (ButtonReleased())    {
  329.         int mx, my;
  330.         GetPosition(mx, my);
  331.         DFWindow *Mwnd;
  332.         if ((Mwnd = MouseWindow(mx, my)) == NULL)
  333.             return;
  334.         // ------- disable typematic check
  335.         clickx = clicky = -1;
  336.            delaytimer.DisableTimer();
  337.         // ------- the button was released
  338.         if (mx == releasex && my == releasey)    {
  339.             // ---- same position as last left button release
  340.             if (doubletimer.TimerRunning())    {
  341.                 // -- second click before double timeout
  342.                 doubletimer.DisableTimer();
  343.                 Mwnd->DoubleClick(mx, my);
  344.                 releasex = releasey = -1;
  345.             }
  346.         }
  347.         else    {
  348.             doubletimer.SetTimer(DOUBLETICKS);
  349.             Mwnd->ButtonReleased(mx, my);
  350.                releasex = mx;
  351.                releasey = my;
  352.         }
  353.     }
  354. }
  355. void Mouse::DispatchMove()
  356. {
  357.     if (Moved())    {
  358.         int mx, my;
  359.         GetPosition(mx, my);
  360.         DFWindow *Mwnd;
  361.         if ((Mwnd = MouseWindow(mx, my)) != NULL)    {
  362.             Mwnd->MouseMoved(mx, my);
  363.             clickx = clicky = -1;
  364.         }
  365.     }
  366. }
  367. void Mouse::DispatchLeftButton()
  368. {
  369.     if (LeftButton())    {
  370.         int mx, my;
  371.         GetPosition(mx, my);
  372.         DFWindow *Mwnd;
  373.         if ((Mwnd = MouseWindow(mx, my)) == NULL)
  374.             return;
  375.         if (mx == clickx && my == clicky)    {
  376.             if (delaytimer.TimedOut())    {
  377.                 // ---- button held down a while
  378.                 delaytimer.SetTimer(DELAYTICKS);
  379.                 // ---- post a typematic-like button
  380.                 Mwnd->LeftButton(mx, my);
  381.             }
  382.         }
  383.         else    {
  384.             // --------- new button press
  385.             delaytimer.SetTimer(FIRSTDELAY);
  386.             if (Mwnd->SetFocus())
  387.                 Mwnd->LeftButton(mx, my);
  388.             clickx = mx;
  389.                clicky = my;
  390.         }
  391.     }
  392. }
  393. // -------- dispatch mouse events
  394. void Mouse::DispatchEvent()
  395. {
  396.     DispatchRelease();
  397.     DispatchMove();
  398.     DispatchLeftButton();
  399. }
  400.  
  401.  
  402.  
  403.  
  404. [LISTING FOUR]
  405.  
  406. // ------------ cursor.cpp
  407.  
  408. #include <dos.h>
  409. #include "cursor.h"
  410. #include "desktop.h"
  411.  
  412. Cursor::Cursor()
  413. {
  414.     cs = 0;
  415.     Save();
  416. }
  417. Cursor::~Cursor()
  418. {
  419.     Restore();
  420. }
  421. // ------ get cursor shape and position
  422. void Cursor::GetCursor()
  423. {
  424.     regs.h.ah = READCURSOR;
  425.     regs.x.bx = desktop.screen().Page();
  426.     int86(VIDEO, ®s, ®s);
  427. }
  428. // -------- get the current cursor position
  429. void Cursor::GetPosition(int &x, int &y)
  430. {
  431.     GetCursor();
  432.     x = regs.h.dl;
  433.     y = regs.h.dh;
  434. }
  435. // ------ position the cursor
  436. void Cursor::SetPosition(int x, int y)
  437. {
  438.     regs.x.dx = ((y << 8) & 0xff00) + x;
  439.     regs.h.ah = SETCURSOR;
  440.     regs.x.bx = desktop.screen().Page();
  441.     int86(VIDEO, ®s, ®s);
  442. }
  443. // ------ save the current cursor configuration
  444. void Cursor::Save()
  445. {
  446.     if (cs < MAXSAVES)    {
  447.         GetCursor();
  448.         cursorshape[cs] = regs.x.cx;
  449.         cursorpos[cs] = regs.x.dx;
  450.         cs++;
  451.     }
  452. }
  453. // ---- restore the saved cursor configuration
  454. void Cursor::Restore()
  455. {
  456.     if (cs)    {
  457.         --cs;
  458.         regs.x.dx = cursorpos[cs];
  459.         regs.h.ah = SETCURSOR;
  460.         regs.x.bx = desktop.screen().Page();
  461.         int86(VIDEO, ®s, ®s);
  462.         SetType(cursorshape[cs]);
  463.     }
  464. }
  465. /* ---- set the cursor type ---- */
  466. void Cursor::SetType(unsigned t)
  467. {
  468.     regs.h.ah = SETCURSORTYPE;
  469.     regs.x.bx = desktop.screen().Page();
  470.     regs.x.cx = t;
  471.     int86(VIDEO, ®s, ®s);
  472. }
  473. /* ----- swap the cursor stack ------- */
  474. void Cursor::SwapStack()
  475. {
  476.     if (cs > 1)    {
  477.         swap(cursorpos[cs-2], cursorpos[cs-1]);
  478.         swap(cursorshape[cs-2], cursorshape[cs-1]);
  479.     }
  480. }
  481. /* ------ hide the cursor ------ */
  482. void Cursor::Hide()
  483. {
  484.     GetCursor();
  485.     regs.h.ch |= HIDECURSOR;
  486.     regs.h.ah = SETCURSORTYPE;
  487.     int86(VIDEO, ®s, ®s);
  488. }
  489. /* ------ show the cursor ------ */
  490. void Cursor::Show()
  491. {
  492.     GetCursor();
  493.     regs.h.ch &= ~HIDECURSOR;
  494.     regs.h.ah = SETCURSORTYPE;
  495.     int86(VIDEO, ®s, ®s);
  496. }
  497.  
  498.  
  499.  
  500. [LISTING FIVE]
  501.  
  502. // ----------- keyboard.cpp
  503.  
  504. #include <stdio.h>
  505. #include <bios.h>
  506. #include <dos.h>
  507. #include "desktop.h"
  508.  
  509. /* ----- table of alt keys for finding shortcut keys ----- */
  510. static int altconvert[] = {
  511.     ALT_A,ALT_B,ALT_C,ALT_D,ALT_E,ALT_F,ALT_G,ALT_H,
  512.     ALT_I,ALT_J,ALT_K,ALT_L,ALT_M,ALT_N,ALT_O,ALT_P,
  513.     ALT_Q,ALT_R,ALT_S,ALT_T,ALT_U,ALT_V,ALT_W,ALT_X,
  514.     ALT_Y,ALT_Z,ALT_0,ALT_1,ALT_2,ALT_3,ALT_4,ALT_5,
  515.     ALT_6,ALT_7,ALT_8,ALT_9
  516. };
  517. /* ---- Test for keystroke ---- */
  518. #ifndef MSC
  519. Bool Keyboard::KeyHit()
  520. {
  521.     _AH = 1;
  522.     geninterrupt(KEYBRD);
  523.     return (Bool)((_FLAGS & ZEROFLAG) == 0);
  524. }
  525. #else
  526. Bool Keyboard::KeyHit()
  527. {
  528.     return (Bool) (bioskey(1) != 0);
  529. }
  530. #endif
  531. /* ---- Read a keystroke ---- */
  532. int Keyboard::GetKey()
  533. {
  534.     int c;
  535.     while (KeyHit() == False)
  536.         ;
  537.     if (((c = bioskey(0)) & 0xff) == 0)
  538.         c = (c >> 8) | 0x1080;
  539.     else
  540.         c &= 0xff;
  541.     return c & 0x10ff;
  542. }
  543. /* ---------- read the keyboard shift status --------- */
  544. int Keyboard::GetShift()
  545. {
  546.     regs.h.ah = 2;
  547.     int86(KEYBRD, ®s, ®s);
  548.     return regs.h.al;
  549. }
  550. /* ------ convert an Alt+ key to its letter equivalent ----- */
  551. int Keyboard::AltConvert(int c)
  552. {
  553.     int i, a = 0;
  554.     for (i = 0; i < 36; i++)
  555.         if (c == altconvert[i])
  556.             break;
  557.     if (i < 26)
  558.         a = 'a' + i;
  559.     else if (i < 36)
  560.         a = '0' + i - 26;
  561.     return a;
  562. }
  563. Bool Keyboard::ShiftChanged()
  564. {
  565.     int sk = GetShift();
  566.     Bool rtn = (Bool) (sk != shift);
  567.     shift = sk;
  568.     return rtn;
  569. }
  570. // ------ dispatch keyboard events
  571. void Keyboard::DispatchEvent()
  572. {
  573.     // ---- find window for keyboard events
  574.     DFWindow *Kwnd = desktop.FocusCapture() ?
  575.                      desktop.FocusCapture() :
  576.                      desktop.InFocus() ?
  577.                      desktop.InFocus() : desktop.ApplWnd();
  578.     if (ShiftChanged())
  579.            // ---- the shift status changed
  580.         Kwnd->ShiftChanged(GetShift());
  581.     if (KeyHit())
  582.         // --- a key was pressed
  583.         Kwnd->Keyboard(GetKey());
  584. }
  585.  
  586.  
  587.  
  588.  
  589. [LISTING SIX]
  590.  
  591. // -------- speaker.cpp
  592.  
  593. #include <dos.h>
  594. #include <conio.h>
  595. #include "speaker.h"
  596. #include "dflatdef.h"
  597.  
  598. // -------- sound a tone
  599. void Speaker::Beep()
  600. {
  601.     outp(0x43, 0xb6);               // program the frequency
  602.     outp(0x42, (int) (COUNT % 256));
  603.     outp(0x42, (int) (COUNT / 256));
  604.     outp(0x61, inp(0x61) | 3);      // start the sound
  605.     // -------- wait two clock ticks
  606.     const int far *clk = (int far *) MK_FP(0x40,0x6c);
  607.     int then = *clk+2;
  608.     while (*clk < then)
  609.         ;
  610.     outp(0x61, inp(0x61) & ~3);     // stop the sound
  611. }
  612.  
  613.  
  614. [LISTING SEVEN]
  615.  
  616. // ------- clock.cpp
  617.  
  618. #include "desktop.h"
  619.  
  620. Clock::Clock()
  621. {
  622.     clocktimer.SetTimer(0);
  623. }
  624. void Clock::DispatchEvent()
  625. {
  626.     if (clocktimer.TimedOut())    {
  627.         // -------- reset the timer
  628.         clocktimer.SetTimer(19);    // approx. 19 tics/second
  629.         // -------- post the clock event
  630.         if (desktop.ApplWnd() != NULL)
  631.             desktop.ApplWnd()->ClockTick();
  632.     }
  633. }
  634.  
  635.